﻿using System;
using System.Collections.Generic;
using System.Management;
using System.Xml.Serialization;
using System.Linq;
using System.Text;
using System.Reflection;

namespace OSList
{
    /// <summary>
    /// Class loads and returns a list of applications from a specified machine
    /// using WMI services
    /// </summary>
    [Serializable]
    public class OSList : List<OSystem>
    {
        #region Private Properties
        /// <summary>
        /// Contains the remote machine name to connect to
        /// </summary>
        private string remoteHostName;

        /// <summary>
        /// Contains the user name to authenticate with
        /// </summary>
        private string userName;

        /// <summary>
        /// Contains the password to authenticate with
        /// </summary>
        private string password;

        /// <summary>
        /// Contains an error message received from connecting to host
        /// </summary>
        private string errorMessage;
        #endregion

        #region Public Constructors
        /// <summary>
        /// Initializes a new instance of the ApplicationsList class
        /// </summary>
        /// <param name="remoteHostName">Contains the host machine to connect to</param>
        /// <param name="userName">Contains the user name to authenticate with</param>
        /// <param name="password">Contains the password to authenticate with</param>
        public OSList(string remoteHostName, string userName, string password)
        {
            this.remoteHostName = remoteHostName;
            this.userName = userName;
            this.password = password;
            this.errorMessage = string.Empty;
            this.InitializeList();
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Gets any errors returned from connecting to the specified machine and loading 
        /// the applications list 
        /// </summary>
        [XmlIgnoreAttribute]
        public string ErrorMessage
        {
            get
            {
                return this.errorMessage;
            }
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Connects to the specified host and retrieves the applications, populating
        /// the list object
        /// </summary>
        private void InitializeList()
        {
            ManagementScope wmiService = null;
            ConnectionOptions wmiServiceOptions = new ConnectionOptions();
            string connectionString = string.Format("\\\\{0}\\root\\cimv2", this.remoteHostName);

            if (this.remoteHostName != "." && this.remoteHostName != "localhost" && this.userName != "$using current credentials")
            {
                wmiServiceOptions.Impersonation = ImpersonationLevel.Impersonate;
                wmiServiceOptions.Authentication = AuthenticationLevel.PacketPrivacy;
                wmiServiceOptions.Username = this.userName;
                wmiServiceOptions.Password = this.password;
                wmiService = new ManagementScope(connectionString, wmiServiceOptions);
            }
            else
            {
                wmiServiceOptions.Impersonation = ImpersonationLevel.Impersonate;
                wmiServiceOptions.Authentication = AuthenticationLevel.PacketPrivacy;
                wmiService = new ManagementScope(connectionString, wmiServiceOptions);
            }

            try
            {
                wmiService.Connect();

                if (wmiService.IsConnected)
                {
                    ObjectQuery softwareQuery = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
                    ManagementObjectSearcher querySearch = new ManagementObjectSearcher(wmiService, softwareQuery);

                    // Get the results
                    ManagementObjectCollection softwareResults = querySearch.Get();
                    if (softwareResults.Count > 0)
                    {
                        foreach (ManagementBaseObject softwareItem in softwareResults)
                        {
                            OSystem newItem = this.ConvertToAppItem(softwareItem);
                            if (newItem != null)
                            {
                                this.Add(newItem);
                            }
                        }
                        Console.WriteLine("placeholder");
                    }
                }
                else
                {
                    this.errorMessage = string.Format("Unable to connect to {0} as user {1}", this.remoteHostName, this.userName);
                }
            }
            catch (Exception ex)
            {

                this.errorMessage = ex.Message;
            }
        }

        /// <summary>
        /// Converts a returned ManagementBaseObject into an ApplicationItem object
        /// </summary>
        /// <param name="baseObject">The ManagementBaseObject to convert</param>
        /// <returns>Returns an ApplicationItem object</returns>
        private OSystem ConvertToAppItem(ManagementBaseObject baseObject)
        {
            OSystem resultItem = null;
            if (baseObject != null)
            {
                resultItem = new OSystem();
                try
                {
                    Type t = resultItem.GetType();

                    foreach (PropertyInfo p in t.GetProperties())
                    {
                        //p.GetValue(temp[i].appitemz[k], null).ToString()
                        if (p.PropertyType == typeof(int))
                        {
                            try
                            {
                                if (p.Name.ToString().ToLower().Contains("number"))
                                {
                                    System.Diagnostics.Debug.WriteLine(p.Name);
                                }
                                int att = System.Convert.ToInt32(this.FixString(baseObject.Properties[p.Name].Value), null);
                                p.SetValue(resultItem, att, null);
                            }
                            catch
                            {

                            }
                        }
                        else
                        {

                            try
                            {
                                p.SetValue(resultItem, this.FixString(baseObject.Properties[p.Name].Value.ToString()), null);
                            }
                            catch
                            {

                            }
                        }

                    }
                    //safe values
                    //resultItem.BootDevice = this.FixString(baseObject.Properties["BootDevice"]);
                    //resultItem.Name = this.FixString(baseObject.Properties["Name"].Value);
                    //resultItem.Caption = this.FixString(baseObject.Properties["Caption"].Value);
                    //resultItem.CSName = this.FixString(baseObject.Properties["CSName"].Value);
                    //resultItem.Desc = this.FixString(baseObject.Properties["Description"].Value);
                    //resultItem.InstallDate = this.FixString(baseObject.Properties["InstallDate"].Value);
                    ////resultItem.InstallDate2 = !string.IsNullOrEmpty(resultItem.InstallDate) ? Convert.ToDateTime(resultItem.InstallDate) : DateTime.MinValue;
                    //resultItem.FixComment = this.FixString(baseObject.Properties["FixComments"].Value);
                    //resultItem.HotFixID = this.FixString(baseObject.Properties["HotFixID"].Value);
                    //resultItem.InstallBy = this.FixString(baseObject.Properties["InstalledBy"].Value);
                    //resultItem.InstalledOn = this.FixString(baseObject.Properties["InstalledOn"].Value);
                    //resultItem.ServicePack = this.FixString(baseObject.Properties["ServicePackInEffect"].Value);

                    ////unsafe
                    //try { resultItem.Status = this.FixString(baseObject.Properties["Status"].Value); }
                    //catch { };
                }
                catch (Exception e1)
                {
                    if (e1.Message.ToLower().Contains("not found"))
                    {

                    }
                }
            }

            return resultItem;
        }

        /// <summary>
        /// Converts values to strings, null values are returned as empty strings
        /// </summary>
        /// <param name="data">The object to convert</param>
        /// <returns>Returns a string version of the object value</returns>
        private string FixString(object data)
        {
            string resultValue = string.Empty;

            if (data != null)
            {
                resultValue = Convert.ToString(data);
            }

            return resultValue;
        }

        /// <summary>
        /// Converts a string value to an integer value
        /// </summary>
        /// <param name="data">The string value to convert to int</param>
        /// <returns>Returns integer value of string, 0 if invalid</returns>
        private int FixInteger(string data)
        {
            int resultValue = 0;

            if (data != null)
            {
                int.TryParse(data, out resultValue);
            }

            return resultValue;
        }
        #endregion
    }
}




  